home *** CD-ROM | disk | FTP | other *** search
/ SPACE 1 / SPACE - Library 1 - Volume 1.iso / program / 168 / library / fmtio.c next >
C/C++ Source or Header  |  1988-04-30  |  12KB  |  578 lines

  1. /* C library - printf/scanf guts */
  2.  
  3. #define FILE    char
  4. #define EOF    -1
  5. #define EOS    0
  6. #define NULL    0L
  7.  
  8. /* printf's (see below for the guts) */
  9.  
  10. char *_dopf();
  11.  
  12. fprintf(fp, fmt, args) FILE *fp; char *fmt; int args; {
  13.     extern char _pfb[256];
  14.     _dopf(_pfb, fmt, &args);
  15.     return fputs(_pfb, fp);
  16. }
  17.  
  18. printf(fmt, args) char *fmt; int args; {
  19.     extern char _pfb[256];
  20.     extern FILE *stdout;
  21.     _dopf(_pfb, fmt, &args);
  22.     return fputs(_pfb, stdout);
  23. }
  24.  
  25. /* scanf routines */
  26.  
  27. fscanf(f, fmt, args) FILE *f; char *fmt; int *args; {
  28.     extern char *_sfcp;
  29.     extern FILE *_sffp;
  30.     _sffp = f;
  31.     _sfcp = NULL;
  32.     return _dosf(fmt, &args);
  33. }
  34.  
  35. scanf(fmt, args) char *fmt; int *args; {
  36.     extern char *_sfcp;
  37.     extern FILE *_sffp, *stdin;
  38.     _sffp = stdin;
  39.     _sfcp = NULL;
  40.     return _dosf(fmt, &args);
  41. }
  42.  
  43. sscanf(s, fmt, args) char *s; char *fmt; int *args; {
  44.     extern char *_sfcp;
  45.     extern FILE *_sffp;
  46.     _sffp = NULL;
  47.     _sfcp = s;
  48.     return _dosf(fmt, &args);
  49. }
  50.         
  51. /* the guts of the scanf's */
  52.  
  53. _dosf(fmt, args) char *fmt; int **args; {
  54.     int assigned, wid, lng, skip, *ip, f, c, m, base;
  55.     extern char _pfb[1];
  56.     long n, *lp, atof();
  57.     char *cp;
  58.     assigned = 0;
  59.     c = _sfget();
  60.     while ((f = *fmt++) && c != EOF) {
  61.         if (f <= ' ') { /* skip spaces */
  62.             while (c <= ' ' && c != EOF)
  63.                 c = _sfget();
  64.         }
  65.         else if (f != '%') { /* match character */
  66.             if (c != f) 
  67.                 return assigned;
  68.             c = _sfget();
  69.         }
  70.         else    {
  71.             wid = lng = skip = 0;
  72.             if ((f = *fmt++) == '*') { /* skip assignment */
  73.                 skip++;
  74.                 f = *fmt++;
  75.             }
  76.             while (f >= '0' && f <= '9') { /* width of value */
  77.                 wid = wid * 10 + f - '0';
  78.                 f = *fmt++;
  79.             }
  80.             if (f == 'l') { /* long */
  81.                 lng++;
  82.                 f = *fmt++;
  83.             }
  84.             else if (f == 'h') { /* short */
  85.                 f = *fmt++;
  86.             }
  87.             switch (f) { /* conversion spec */
  88.             case '%':
  89.                 if (c != '%') return assigned;
  90.                 c = _sfget();
  91.                 break;
  92.             case 'c':
  93.                 if (wid == 0) {
  94.                     cp = *args++;
  95.                     if (!skip) {
  96.                         *cp = c;
  97.                         assigned++;
  98.                     }
  99.                     c = _sfget();
  100.                     break;
  101.                 }
  102.             case 's':
  103.                 cp = *args++;
  104.                 while (c <= ' ' && c != EOF)
  105.                     c = _sfget();
  106.                 while (c > ' ' && c != EOF) {
  107.                     if (!skip) *cp++ = c;
  108.                     c = _sfget();
  109.                     if (--wid == 0) break;
  110.                 }
  111.                 *cp = 0;
  112.                 if (!skip) assigned++;
  113.                 break;
  114.             case 'D': case 'X': case 'O':
  115.                 lng = 1;
  116.                 f = f - 'A' + 'a';
  117.             case 'd': case 'x': case 'o':
  118.                 base = (f == 'x' ? 16 : f == 'o' ? 8 : 10);
  119.                 n = 0L;
  120.                 while (c != EOF && c <= ' ')
  121.                     c = _sfget();
  122.                 if ((m = _sfnum(c, base)) < 0)
  123.                     return assigned;
  124.                 do    {
  125.                     n = n * base + m;
  126.                     c = _sfget();
  127.                     m = _sfnum(c, base);
  128.                     if (--wid == 0) break;
  129.                 } while (m >= 0);
  130.                 if (m >= 0) c = _sfget();
  131.                 if (!skip) {
  132.                     if (lng) {
  133.                         lp = *args++;
  134.                         *lp = n;
  135.                     }
  136.                     else    {
  137.                         ip = *args++;
  138.                         *ip = n;
  139.                     }
  140.                     assigned++;
  141.                 }
  142.                 break;
  143.             case 'e': case 'f': case 'E': case 'F':
  144.                 while (c <= ' ' && c != EOF)
  145.                     c = _sfget();
  146.                 if (!_sfflt(c))
  147.                     return assigned;
  148.                 for (cp = _pfb; _sfflt(c); ) {
  149.                     *cp++ = c;
  150.                     c = _sfget();
  151.                 }
  152.                 *cp = 0;
  153.                 if (!skip) {
  154.                     lp = *args++;
  155.                     *lp = atof(_pfb);
  156.                     assigned++;
  157.                 }
  158.                 break;
  159.             default:
  160.                 return assigned;
  161.             }
  162.         }
  163.     }
  164.     return f == 0 ? assigned : EOF;
  165. }
  166.  
  167.  
  168. _sfnum(c, base) {
  169.     if (c >= '0' && c <= '9')
  170.         return c - '0';
  171.     else if (base == 16 && c >= 'a' && c <= 'f')
  172.         return c - 'a' + 10;
  173.     else if (base == 16 && c >= 'A' && c <= 'F')
  174.         return c - 'A' + 10;
  175.     else     return -1;
  176. }
  177.  
  178. _sfflt(c) { /* pretty lame parser for float numbers, but so it goes */
  179.     if (c >= '0' && c <= '9') return 1;
  180.     if (c == '+' || c == '-' || c == '.') return 1;
  181.     if (c == 'e' || c == 'E') return 1;
  182.     return 0;
  183. }
  184.  
  185. _sfget() {
  186.     extern char *_sfcp;
  187.     extern FILE *_sffp;
  188.     if (_sffp) return getc(_sffp);
  189.     if (_sfcp && *_sfcp) return *_sfcp++;
  190.     return EOF;
  191. }
  192.  
  193. char *_sfcp;    /* char pointer for scanf input string */
  194. FILE *_sffp;    /* FILE pointer for scanf input stream */
  195.  
  196. /* guts of the printf stuff */
  197.  
  198. #define    MINUSFLG    1
  199. #define    PLUSFLG        2
  200. #define    BLANKFLG    4
  201. #define    POUNDFLG    8
  202. #define    ZEROFLG        16
  203. #define    LONGFLG        32
  204. #define    SIGNFLG        64
  205. #define    LOWERFLG    128
  206.  
  207. #define    MAXINT    32767
  208.  
  209. char    _pfb[256];    /* in case someone needs a buffer */
  210.  
  211. sprintf(buf, fmt, args)    char *buf, *fmt; int args; {
  212.     return _dopf(buf, fmt, &args) - buf;
  213. }
  214.  
  215. char *_numcnv(), *_fltcnv();
  216.  
  217. char *
  218. _dopf(buf, fmt, i_p) char *buf, *fmt; int *i_p; {
  219.     char    c, **s_p, *s;
  220.     long    strtol();
  221.     int    i, lng, precision, minfldw, flags;
  222.  
  223.     for (c = *fmt; ; c = *++fmt) {
  224.         /* scan to next conversion specification */
  225.         while (c != '%') {
  226.             *buf++ = c;
  227.             if (c == EOS) {
  228.                 return buf - 1;
  229.             }
  230.             c = *++fmt;
  231.         }
  232.         c = *++fmt;
  233.         /* scan flags */
  234.         for (flags = 0; ; c = *++fmt) {
  235.             if (c == '-') flags |= MINUSFLG;
  236.             else if (c == '+') flags |= PLUSFLG;
  237.             else if (c == ' ') flags |= BLANKFLG;
  238.             else if (c == '#') flags |= POUNDFLG;
  239.             else break;
  240.         }
  241.         /* scan minimum field width */
  242.         if (c == '*') {
  243.             minfldw = *i_p++;
  244.             c = *++fmt;
  245.         }
  246.         else    {
  247.             if (c == '0') flags |= ZEROFLG;
  248.             minfldw = (int)strtol(fmt, &fmt, 10);
  249.             c = *fmt;
  250.         }
  251.         /* scan precision */
  252.         precision = -1;
  253.         if (c == '.') {
  254.             c = *++fmt;
  255.             if (c == '*') {
  256.                 precision = *i_p++;
  257.                 c = *++fmt;
  258.             }
  259.             else    {
  260.                 precision = (int)strtol(fmt, &fmt, 10);
  261.                 c = *fmt;
  262.             }
  263.         }
  264.         if (c == 'l') {
  265.             flags |= LONGFLG;
  266.             c = *++fmt;
  267.         }
  268.         switch (c) {
  269.         case 'd':
  270.             buf = _numcnv(buf, 10, flags | SIGNFLG, &i_p,
  271.                 precision, minfldw);
  272.             break;
  273.         case 'o':
  274.             buf = _numcnv(buf, 8, flags, &i_p, precision, minfldw);
  275.             break;
  276.         case 'u':
  277.             buf = _numcnv(buf, 10, flags, &i_p, precision, minfldw);
  278.             break;
  279.         case 'x':
  280.             flags |= LOWERFLG;
  281.         case 'X':
  282.             buf = _numcnv(buf, 16, flags, &i_p, precision, minfldw);
  283.             break;
  284.         case 'f':
  285.             buf = _fltcnv(buf, 'f', flags, &i_p, 
  286.                     precision, minfldw);
  287.             break;
  288.         case 'e':
  289.             flags |= LOWERFLG;
  290.         case 'E':
  291.             buf = _fltcnv(buf, 'E', flags, &i_p, 
  292.                     precision, minfldw);
  293.             break;
  294.         case 'g':
  295.             flags |= LOWERFLG;
  296.         case 'G':
  297.             buf = _fltcnv(buf, 'G', flags, &i_p, precision, minfldw);
  298.             break;
  299.         case 'c':
  300.             *buf++ = *i_p++;
  301.             break;
  302.         case 's':
  303.             if (precision < 0) precision = MAXINT;
  304.             s_p = (char **)i_p;
  305.             s = *s_p++;
  306.             i_p = (int *)s_p;
  307.             for (lng = 0; s[lng] != EOS && lng < precision; ++lng);
  308.             i = minfldw - lng;
  309.             if ((flags & MINUSFLG) == 0) { /* right justify */
  310.                 while (i-- > 0) *buf++ = ' ';
  311.             }
  312.             while (lng--) *buf++ = *s++;
  313.             while (i-- > 0) *buf++ = ' ';
  314.             break;
  315.         case '%':
  316.         default:
  317.             *buf++ = c;
  318.             break;
  319.         }
  320.     }
  321. }
  322.  
  323. /* 
  324.  * convert float to ascii for my 32 bit floating point format
  325.  *    bit    function
  326.  *    31    sign
  327.  *    24-30    exponent (excess 64)
  328.  *    0-23    fraction
  329.  */
  330.  
  331. #define EXCESS    64
  332. #define DIGITS    24
  333. #define MAXFRAC    0xFFFFFF
  334. #define MAXEXP    0x7F
  335. #define MAXBITS    32
  336.  
  337. #define sign(x) ((x >> 31) & 1)
  338. #define exp(x) (((x >> 24) & MAXEXP) - EXCESS)
  339. #define frac(x) (x & MAXFRAC)
  340. #define negate(x) (x ^ 0x80000000L)
  341.  
  342. char *
  343. _fltcnv(buf, style, flags, f_p, precision, minfldw) 
  344.     char     *buf;
  345.     int    style;
  346.     int    flags;
  347.     long    **f_p;
  348.     int     precision;
  349.     int    minfldw;
  350. {
  351.     long    x;
  352.     int     e, ee, len;
  353.     char     ibuf[15], fbuf[15], ebuf[6], sbuf[2], *p, *r;
  354.     unsigned long f, t, b, d;
  355.  
  356.     x = **f_p;
  357.     *f_p += 1;
  358.     *ibuf = *fbuf = *sbuf = *ebuf = 0;
  359.     if (precision < 0)
  360.         precision = 6;
  361.     else if (precision > 13)
  362.         precision = 13;
  363.     if (x == 0L) {
  364.         strcpy(ibuf, "0");
  365.         if (precision > 0)
  366.             strcpy(fbuf, ".0");
  367.     }
  368.     else    {
  369.         if (sign(x))
  370.             strcpy(sbuf, "-");
  371.         else if (flags & PLUSFLG)
  372.             strcpy(sbuf, "+");
  373.         else if (flags & BLANKFLG)
  374.             strcpy(sbuf, " ");
  375.         e = exp(x);
  376.         f = frac(x);
  377.         if (style == 'E' || e >= MAXBITS || e <= -DIGITS) {
  378.             ee = 0;
  379.             while (e > 2) {
  380.                 d = f % 10L;
  381.                 f = f / 10L;
  382.                 while (f && (f & 0x800000L) == 0) {
  383.                     f <<= 1;
  384.                     e--;
  385.                 }
  386.                 f += d;
  387.                 ee++;
  388.             }
  389.             while (e < 0) {
  390.                 f = f * 10L;
  391.                 d = 0L;
  392.                 while (f & 0xFF000000L) {
  393.                     d |= (f & 1L);
  394.                     f >>= 1;
  395.                     e++;
  396.                 }
  397.                 f += d;
  398.                 ee--;
  399.             }
  400.             ebuf[0] = flags & LOWERFLG ? 'e' : 'E';
  401.             if (ee < 0) {
  402.                 ebuf[1] = '-';
  403.                 ee = -ee;
  404.             }
  405.             else    ebuf[1] = '+';
  406.             ebuf[2] = (ee / 10) + '0';
  407.             ebuf[3] = (ee % 10) + '0';
  408.             ebuf[4] = 0;
  409.         }
  410.         /* now get the integer part */
  411.         if (e > 0) {
  412.             if (e > DIGITS)
  413.                 t = f << (e - DIGITS);
  414.             else    t = f >> (DIGITS - e);
  415.             _ltoc(t, ibuf);
  416.             f = (f << e) & MAXFRAC;
  417.             e = 0;
  418.         }
  419.         else    {
  420.             strcpy(ibuf, "0");
  421.             if (e < 0)
  422.                 f = f >> -e;
  423.         }
  424.         /* now get the fraction part */
  425.         if (precision > 0) {
  426.             if (f) {
  427.                 b = 0x800000;
  428.                 d =  500000000;
  429.                 t = 1000000000;
  430.                 while (b) {
  431.                     if (f & b)
  432.                         t += d;
  433.                     b >>= 1;
  434.                     d >>= 1;
  435.                 }
  436.                 _ltoc(t, fbuf);
  437.                 fbuf[0] = '.';
  438.             }
  439.             else     strcpy(fbuf, ".0");
  440.         }
  441.     }
  442.     /* adjust the fraction part, trailing 0's, etc */
  443.     if (*fbuf) {
  444.         for (e = strlen(fbuf); e < 15; e++)
  445.             fbuf[e] = '0';
  446.         fbuf[precision+1] = 0;
  447.         if (!((flags & POUNDFLG) && style == 'G')) {
  448.             /* drop trailing 0's */
  449.             for (e = precision; e > 0 && fbuf[e] == '0'; e--)
  450.                 fbuf[e] = 0;
  451.             if (e == 0) 
  452.                 *fbuf = 0;
  453.         }
  454.     }
  455.     /* okay, now fill out buf with the number */
  456.     r = buf;
  457.     len = strlen(ibuf) + strlen(fbuf) + strlen(ebuf) + strlen(sbuf);
  458.     if (flags & MINUSFLG) {
  459.         while (len < minfldw) {
  460.             *buf++ = ' ';
  461.             len++;
  462.         }
  463.     }
  464.     if (*sbuf) 
  465.         *buf++ = *sbuf;
  466.     for (p = ibuf; *buf = *p++; )
  467.         buf++;
  468.     if (*fbuf) {
  469.         for (p = fbuf; *buf = *p++; )
  470.             buf++;
  471.     }
  472.     else if (flags & BLANKFLG)
  473.         *buf++ = '.';
  474.     if (*ebuf) {
  475.         for (p = ebuf; *buf = *p++; )
  476.             buf++;
  477.     }
  478.     if ((flags & MINUSFLG) == 0) {
  479.         while (len < minfldw) {
  480.             *buf++ = ' ';
  481.             len++;
  482.         }
  483.     }
  484.     *buf = 0;
  485.     return buf;
  486. }
  487.  
  488. _ltoc(x, p) long x; char *p; {
  489.     char *r;
  490.     int i, j, t;
  491.     r = p;
  492.     if (x == 0) {
  493.         *p++ = '0';
  494.         *p = 0;
  495.     }
  496.     else    {
  497.         if (x < 0) {
  498.             *p++ = '-';
  499.             x = -x;
  500.         }
  501.         for (i = 0; x > 0; x = x / 10L)
  502.             p[i++] = (x % 10L) + '0';
  503.         p[i--] = 0;
  504.         for (j = 0; j < i; ) {
  505.             t = p[i];
  506.             p[i--] = p[j];
  507.             p[j++] = t;
  508.         }
  509.     }
  510. }
  511.  
  512. char *
  513. _numcnv(buf, base, flags, ip_p, precision, minfldw)
  514.     char    *buf;
  515.     unsigned int    base;
  516.     int    **ip_p;
  517. {
  518.     char    numbuf[20], prefix[5], *s, *p, *strncpy();
  519.     int    n, pad, lng, d;
  520.     long    value, *l_p;
  521.     unsigned long    uvalue;
  522.  
  523.     s = numbuf;
  524.     p = prefix;
  525.     if (flags & LONGFLG) {
  526.         l_p = (long *)*ip_p;
  527.         value = *l_p++;
  528.         *ip_p = (int *)l_p;
  529.     }
  530.     else    {
  531.         value = (long)**ip_p;
  532.         *ip_p += 1;
  533.     }
  534.     if (flags & SIGNFLG) {
  535.         if (value < 0) {
  536.             *p++ = '-';
  537.             value = -value;
  538.         }
  539.         else    {
  540.             if (flags & PLUSFLG) *p++ = '+';
  541.             else if (flags & BLANKFLG) *p++ = ' ';
  542.         }
  543.     }
  544.     uvalue = (unsigned long) value;
  545.     while (uvalue) {
  546.         d = uvalue % base;
  547.         *s++ = (d < 10) ? d + '0' 
  548.                 : d - 10 + ((flags & LOWERFLG) ? 'a' : 'A');
  549.         uvalue /= base;
  550.     }
  551.     lng = (int)(s - numbuf);
  552.     n = (int)(p - prefix);
  553.     pad = minfldw - n;
  554.     if (flags & ZEROFLG) precision = minfldw - n;
  555.     if (precision < 0) precision = 1;
  556.     if (flags & POUNDFLG) {
  557.         if (base == 8 && lng >= precision) precision = lng + 1;
  558.         else if (base == 16) {
  559.             *p++ = '0';
  560.             *p++ = flags & LOWERFLG ? 'x' : 'X';
  561.             n += 2;
  562.             precision -= 2;
  563.         }
  564.     }
  565.     pad -= lng > precision ? lng : precision;
  566.     if (pad < 0) pad = 0;
  567.     if ((flags & MINUSFLG) == 0) {
  568.         while (pad--) *buf++ = ' ';
  569.         pad = 0;
  570.     }
  571.     strncpy(buf, prefix, n);
  572.     buf += n;
  573.     while (precision-- > lng) *buf++ = '0';
  574.     while (lng--) *buf++ = *--s;
  575.     while (pad--) *buf++ = ' ';
  576.     return    buf;
  577. }
  578.